import os
import time
import subprocess
import threading
import multiprocessing

# 全局变量
g_sim_sta = False  # SIM卡状态
g_net_sta = False  # 驻网状态
g_csq = ''         # 信号强度值，例如 '23,99'

# 状态管理类
class ConnectionState:
    def __init__(self):
        self.read_thread = None
        self.process_thread = None
        self.process = None
        self.parent_conn = None
        self.child_conn = None
        self.stop_event = threading.Event()
        self.lock = threading.Lock()

# 实例化状态对象
conn_state = ConnectionState()

# 读取AT数据线程
def read_data(conn, process):
    try:
        while not conn_state.stop_event.is_set():
            data = process.stdout.readline()
            if data == '' and process.poll() is not None:
                break
            if data:
                conn.send(data)
    except Exception as e:
        print("read_data error:", e)
    finally:
        conn.close()

# 处理AT响应线程
def process_data(conn):
    global g_sim_sta, g_net_sta, g_csq
    try:
        while not conn_state.stop_event.is_set():
            try:
                data = conn.recv()
                if '+CPIN: READY' in data:
                    print('SIM card detected.')
                    g_sim_sta = True
                if '+COPS:' in data:
                    fields = data.split(',')
                    if len(fields) >= 3:
                        print('Network register success.')
                        g_net_sta = True
                if '+CGSN:' in data:
                    s = data.split(':')
                    print('IMEI号:', s[1].strip())
                if '+MCCID:' in data:
                    s = data.split(':')
                    print('ICCID号:', s[1].strip())
                if '+CSQ:' in data:
                    parts = data.split(":")[1].split(",")
                    rssi = parts[0].strip()
                    ber = parts[1].strip()
                    g_csq = rssi
                    # print(f'信号值：{rssi}, BER: {ber}')
            except EOFError:
                print("管道已关闭，处理线程退出")
                break
    finally:
        conn.close()

# 挂载模块
def cat1_mount():
    os.system('echo 0 > /sys/class/gpio/gpio11/value')
    time.sleep(10)

# 取消挂载
def cat1_umount():
    os.system('ifconfig eth0 down')
    os.system('killall -9 udhcpc > /dev/null 2>&1')
    os.system('kill -9 $(ps | grep "cat /dev/ttyUSB2" | grep -v grep | awk \'{print $1}\') > /dev/null 2>&1')
    os.system('echo 1 > /sys/class/gpio/gpio11/value')
    time.sleep(0.3)

# 拨号
def cat1_dialing():
    os.system('echo -e \'ATE0\r\n\' > /dev/ttyUSB2')

    last_print_time = time.time()
    while True:
        os.system('echo -e \'AT+CPIN?\r\n\' > /dev/ttyUSB2')
        if not g_sim_sta:
            current_time = time.time()
            if current_time - last_print_time >= 10:
                print('No SIM card detected....')
                last_print_time = current_time
            time.sleep(1)
        else:
            break

    for i in range(20):
        os.system('echo -e \'AT+COPS?\r\n\' > /dev/ttyUSB2')
        if not g_net_sta:
            time.sleep(1)
            if i == 19:
                print('Network register fail...')
                return False
        else:
            break

    os.system('echo -e \'AT+CGDCONT?\r\n\' > /dev/ttyUSB2')
    os.system('echo -e \'AT+MDIALUP?\r\n\' > /dev/ttyUSB2')
    os.system('echo -e \'AT+MDIALUP=1,1\r\n\' > /dev/ttyUSB2')
    os.system('udhcpc -i eth0')
    time.sleep(3)
    return True

# 获取信息
def get_imei():
    os.system('echo -e \'AT+CGSN=1\r\n\' > /dev/ttyUSB2')

def get_csq():
    os.system('echo -e \'AT+CSQ\r\n\' > /dev/ttyUSB2')

def get_iccid():
    os.system('echo -e \'AT+MCCID\r\n\' > /dev/ttyUSB2')

# 清理旧资源
def cleanup():
    global g_sim_sta, g_net_sta
    with conn_state.lock:
        conn_state.stop_event.set()

        if conn_state.read_thread and conn_state.read_thread.is_alive():
            conn_state.read_thread.join(timeout=1)

        if conn_state.process_thread and conn_state.process_thread.is_alive():
            conn_state.process_thread.join(timeout=1)

        if conn_state.process:
            conn_state.process.terminate()
            conn_state.process.wait()

        if conn_state.parent_conn:
            conn_state.parent_conn.close()
        if conn_state.child_conn:
            conn_state.child_conn.close()

        # 重置状态
        conn_state.read_thread = None
        conn_state.process_thread = None
        conn_state.process = None
        conn_state.parent_conn = None
        conn_state.child_conn = None
        conn_state.stop_event.clear()

        g_sim_sta = False
        g_net_sta = False

# 持续连接逻辑
def connect_4g_forever():
    global g_sim_sta, g_net_sta,g_csq
    try:
        print("尝试建立4G连接...")
        cleanup()  # 先清理旧连接
        g_sim_sta = False
        g_net_sta = False
        g_csq = ''  # 清空信号值
        cat1_mount()

        # 创建新连接
        process = subprocess.Popen(['cat', '/dev/ttyUSB2'], stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE, bufsize=1, universal_newlines=True)
        parent_conn, child_conn = multiprocessing.Pipe()
        read_thread = threading.Thread(target=read_data, args=(child_conn, process))            # 线程1
        process_thread = threading.Thread(target=process_data, args=(parent_conn,))              # 线程2

        with conn_state.lock:
            conn_state.process = process
            conn_state.read_thread = read_thread
            conn_state.process_thread = process_thread
            conn_state.parent_conn = parent_conn
            conn_state.child_conn = child_conn

        read_thread.start()
        process_thread.start()

        dial_success = cat1_dialing()
        if not dial_success:
            raise Exception("拨号失败")

        get_imei()
        time.sleep(1)
        get_csq()
        time.sleep(1)
        get_iccid()
        time.sleep(1)

        print("4G连接成功,保持在线...")

        # 启动监控线程
        monitor_thread = threading.Thread(target=network_monitor, args=(conn_state.stop_event,))     # 线程3
        monitor_thread.daemon = True
        monitor_thread.start()

    except Exception as e:
        print(f"连接失败: {e}")
        cleanup()
        time.sleep(5)
        connect_4g_forever()  # 自动重试

def network_monitor(stop_event):
    last_csq_time = time.time()  # 上次收到 CSQ 的时间

    while not stop_event.is_set():
        time.sleep(10)

        current_time = time.time()

        # 主动发送 AT+CSQ 请求信号值
        os.system('echo -e \'AT+CSQ\\r\\n\' > /dev/ttyUSB2')

        # 判断信号值是否有效
        if g_csq == '':
            print("未收到信号值，可能掉线...")
            if current_time - last_csq_time > 30:
                print("长时间未收到信号值，准备重启模块...")
                cat1_umount()
                connect_4g_forever()
                break
        elif g_csq == '99':
            print("信号值为 99,无服务,准备重启模块...")
            cat1_umount()
            connect_4g_forever()
            break
        else:
            print(f"当前信号值：{g_csq}，状态正常")
            last_csq_time = current_time  # 更新最后收到时间


# def set_airplane_mode(enable):
#     """
#     控制飞行模式的进入和退出
    
#     :param enable: bool类型参数
#                   True - 进入飞行模式（关闭所有无线连接）
#                   False - 退出飞行模式（恢复无线连接）
#     :return: bool - 操作是否成功
#     """
#     try:
#         if enable:
#             print("正在进入飞行模式...")
#             # 进入飞行模式的操作
#             # 1. 停止网络监控
#             cleanup()
#             # 2. 关闭4G模块
#             # cat1_umount()
#             # 3. 发送AT命令关闭射频功能
#             os.system('echo -e \'AT+CFUN=0\\r\\n\' > /dev/ttyUSB2')
#             time.sleep(2)

#             print("已进入飞行模式")
#             return True
            
#         else:
#             print("正在退出飞行模式...")
            
#             # 退出飞行模式的操作
#             # 1. 恢复射频功能
#             os.system('echo -e \'AT+CFUN=1\\r\\n\' > /dev/ttyUSB2')
#             time.sleep(2)
#             print("正在重新建立4G连接...")
#             connect_4g_forever()
        
#             print("已退出飞行模式")
#             return True
            
#     except Exception as e:
#         print(f"飞行模式操作失败: {e}")
#         return False




   